package icu.zhhll.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.StringJoiner;

/**
 * mysql元数据工具类
 *
 * @author zh
 * @date 2023/8/15 18:11
 */
public class MysqlMetaDataUtils {
    private static final String DRIVER5 = "com.mysql.jdbc.Driver";
    private static final String DRIVER6 = "com.mysql.cj.jdbc.Driver";

    private static final Logger LOGGER = LoggerFactory.getLogger(MysqlMetaDataUtils.class);

    static {
        registDriver();
    }

    /**
     * 获取数据库所有表
     *
     * @param url
     * @param username
     * @param password
     * @return
     */
    public static List<String> getTables(String url, String username, String password) {

        try (Connection conn = DriverManager.getConnection(url, username, password)) {
            return getTables(conn);
        } catch (SQLException e) {
            LOGGER.error("获取表失败", e);
        }

        return null;
    }

    /**
     * 获取所有表
     *
     * @param conn
     * @return
     */
    public static List<String> getTables(Connection conn) {

        List<String> tables = new ArrayList<>();

        try {
            DatabaseMetaData dbMetaData = conn.getMetaData();
            try (ResultSet rs = dbMetaData.getTables(null, null, null, new String[]{"TABLE"})) {
                while (rs.next()) {
                    tables.add(rs.getString("TABLE_NAME"));
                }

                return tables;
            }

        } catch (SQLException e) {
            LOGGER.error("获取表失败", e);
        }

        return null;
    }

    /**
     * 获取表字段信息
     *
     * @param conn
     * @param tableName
     * @return
     */
    public static List<Column> getTableColumns(Connection conn, String tableName) {
        List<Column> columns = new ArrayList<>();
        try {
            DatabaseMetaData dbMetaData = conn.getMetaData();
            try (ResultSet rs = dbMetaData.getColumns(null, null, tableName, "%")) {
                while (rs.next()) {
                    Column column = new Column();
                    column.setName(rs.getString("COLUMN_NAME"));
                    column.setType(rs.getString("TYPE_NAME"));
                    column.setSize(rs.getInt("COLUMN_SIZE"));
                    column.setComment(rs.getString("REMARKS"));
                    column.setNullable(rs.getBoolean("NULLABLE"));
                    column.setDefaultValue(rs.getString("COLUMN_DEF"));
                    if (column.getType().toLowerCase(Locale.US).contains("serial")) {
                        column.setAutoIncrement(true);
                    } else {
                        String mysqlResult = rs.getString("IS_AUTOINCREMENT");
                        column.setAutoIncrement(("YES".equals(mysqlResult) || (!"NO".equals(mysqlResult)
                                && rs.getBoolean("IS_AUTOINCREMENT"))));
                    }
                    if (column.getComment() == null) {
                        column.setComment("");
                    }

                    columns.add(column);
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException("获取表信息失败", e);
        }
        return columns;
    }

    private static void registDriver() {
        try {
            Class.forName(DRIVER5);
        } catch (ClassNotFoundException e) {
            try {
                Class.forName(DRIVER6);
            } catch (ClassNotFoundException classNotFoundException) {
                throw new RuntimeException("不存在mysql驱动");
            }
        }
    }

    public static class Column {
        private String name;
        private String type;
        private int size;
        private String defaultValue;
        private String comment;
        private boolean nullable;
        private boolean autoIncrement;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public int getSize() {
            return size;
        }

        public void setSize(int size) {
            this.size = size;
        }

        public String getDefaultValue() {
            return defaultValue;
        }

        public void setDefaultValue(String defaultValue) {
            this.defaultValue = defaultValue;
        }

        public String getComment() {
            return comment;
        }

        public void setComment(String comment) {
            this.comment = comment;
        }

        public boolean isNullable() {
            return nullable;
        }

        public void setNullable(boolean nullable) {
            this.nullable = nullable;
        }

        public boolean isAutoIncrement() {
            return autoIncrement;
        }

        public void setAutoIncrement(boolean autoIncrement) {
            this.autoIncrement = autoIncrement;
        }

        @Override
        public String toString() {
            return new StringJoiner(", ", Column.class.getSimpleName() + "[", "]")
                    .add("name='" + name + "'")
                    .add("type='" + type + "'")
                    .add("size=" + size)
                    .add("defaultValue='" + defaultValue + "'")
                    .add("comment='" + comment + "'")
                    .add("nullable=" + nullable)
                    .add("autoIncrement=" + autoIncrement)
                    .toString();
        }
    }
}
